home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok24.lha / DME / SRC / source.zoo / cmd2.c < prev    next >
C/C++ Source or Header  |  1989-07-03  |  29KB  |  1,179 lines

  1.  
  2. /*
  3.  * CMD2.C   (was TEXT2.C)
  4.  *
  5.  *      (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  */
  7.  
  8. #include "defs.h"
  9. #include <stdio.h>
  10.  
  11. #define nomemory()  {memoryfail = 1;}
  12.  
  13. #if AREXX
  14. #include "rexx.h"
  15. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  16. extern int cmderr;         /* global command error flag for do_rexx()'s use */
  17. #endif
  18.  
  19. extern char MForceTitle;
  20. extern void do_bmove();
  21. extern PROC *proc;
  22.  
  23.  
  24. ED *
  25. uninit_init(ep)
  26. register ED *ep;
  27. {
  28.     short iwinx, iwiny;
  29.     char  tabstop, margin, insertmode, wordwrap;
  30.     FONT  *font;
  31.     long lock = DupLock(ep->dirlock);
  32.  
  33.     iwinx = ep->IWinx;
  34.     iwiny = ep->IWiny;
  35.     tabstop= ep->Tabstop;
  36.     margin = ep->Margin;
  37.     insertmode = ep->Insertmode;
  38.     wordwrap = ep->Wordwrap;
  39.     font = ep->Font;
  40.     ep->Font = NULL;
  41.     text_uninit();
  42.     text_init();
  43.     ep = Ep;
  44.     if (ep->Font)
  45.         CloseFont(ep->Font);
  46.     ep->Font = font;
  47.     ep->IWiny = iwiny;
  48.     ep->IWinx = iwinx;
  49.     ep->Tabstop = tabstop;
  50.     ep->Margin  = margin;
  51.     ep->Insertmode = insertmode;
  52.     ep->Wordwrap = wordwrap;
  53.     ep->Modified = 0;
  54.     ep->Line = ep->Topline = 0;
  55.     UnLock(ep->dirlock);
  56.     ep->dirlock = lock;
  57.     return(ep);
  58. }
  59.  
  60.  
  61. do_remeol()
  62. {
  63.     Current[Clen = Ep->Column] = 0;
  64.     text_sync();
  65.     text_redisplaycurrline();
  66. }
  67.  
  68. do_wleft()
  69. {
  70.     register ED *ep = Ep;
  71.     register ubyte *ptr;
  72.     register int i;
  73.  
  74.     for (;;) {
  75.         i = ep->Column;
  76.         if (i == 0)
  77.             goto prevline;
  78.         --i;
  79.         while (i && !is_ascii(Current[i]))
  80.             --i;
  81.  
  82.         if (!Clen) {
  83. prevline:
  84.             if (Comlinemode || ep->Line == 0) {
  85.                 i = ep->Column;
  86.                 break;
  87.             }
  88.             text_sync();
  89.             --ep->Line;
  90.             text_load();
  91.             ep->Column = Clen;
  92.             continue;
  93.         }
  94.         while (i && is_ascii(Current[i]))
  95.             --i;
  96.         if ( (i != 0) && !is_ascii(Current[i]))
  97.             ++i;
  98.         break;
  99.     }
  100.     ep->Column = i;
  101.     text_sync();
  102. }
  103.  
  104.  
  105. do_wright()
  106. {
  107.     register ubyte *ptr;
  108.     register ED *ep = Ep;
  109.     register int i;
  110.  
  111.     for (;;) {
  112.         i = ep->Column;
  113.         if (i == Clen) {
  114.             if (Comlinemode || ep->Line == ep->Lines - 1) {
  115.                 i = ep->Column;
  116.                 break;
  117.             }
  118.             text_sync();
  119.             ++ep->Line;
  120.             ep->Column = i = 0;
  121.             text_load();
  122.             if ( is_ascii(Current[0]) && (Clen != 0))
  123.                 break;
  124.             continue;
  125.         }
  126.         while (i != Clen && is_ascii(Current[i]))  /* skip past current word */
  127.             ++i;
  128.         while (i != Clen && !is_ascii(Current[i]))  /* to beg. of next word   */
  129.             ++i;
  130.         break;
  131.     }
  132.     ep->Column = i;
  133.     text_sync();
  134. }
  135.  
  136.  
  137. do_split()              /* split line in two at cursor pos */
  138. {
  139.     ubyte buf[256];
  140.     register ED *ep = Ep;
  141.  
  142.     strcpy(buf, Current+ep->Column);
  143.     Current[Clen = ep->Column] = '\0';
  144.     text_sync();
  145.     SetAPen(Rp, 0);
  146.     if (Nsu == 0)
  147.         RectFill(Rp, COL(0), ROW(ep->Line-ep->Topline), Xbase+Xpixs, ROW(ep->Line-ep->Topline+1)-1);
  148.     SetAPen(Rp, 1);
  149.     text_displayseg(ep->Line - ep->Topline, 1);
  150.     do_downadd();
  151.     do_insline();
  152.     strcpy(Current, buf);
  153.     Clen = strlen(Current);
  154.     text_sync();
  155.     text_displayseg(ep->Line - ep->Topline, 1);
  156.     do_up();
  157. }
  158.  
  159. do_join()
  160. {
  161.     register int i = Clen, j;
  162.     register ED *ep = Ep;
  163.  
  164.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253) {
  165.         if (i && Current[i-1] != ' ')
  166.             Current[i++] = ' ';
  167.         strcpy(Current+i, ep->List[ep->Line+1]);
  168.         for (j = i; Current[j] == ' '; ++j);
  169.         for (; i >= 0 && Current[i] == ' '; --i);
  170.         if (j > i+2)
  171.             bmov(Current+j, Current+i+2, strlen(Current+j)+1);
  172.         Clen = strlen(Current);
  173.         text_sync();
  174.         text_displayseg(ep->Line - ep->Topline, 1);
  175.         do_down();
  176.         do_deline();
  177.         do_up();
  178.         return(1);
  179.     }
  180.     return(0);
  181. }
  182.  
  183. do_margin()
  184. {
  185.     Ep->Margin = atoi(av[1]);
  186. }
  187.  
  188. do_wordwrap()
  189. {
  190.     register ED *ep = Ep;
  191.  
  192.     if (av[1][1] == 'n')
  193.         ep->Wordwrap = 1;
  194.     if (av[1][1] == 'f')
  195.         ep->Wordwrap = 0;
  196.     if (av[1][0] == 't')
  197.         ep->Wordwrap = 1 - ep->Wordwrap;
  198.     if (ep->Wordwrap)
  199.         title("Wordwrap ON");
  200.     else
  201.         title("Wordwrap OFF");
  202. }
  203.  
  204. /*
  205.  * n == -1  :   force reformat entire paragraph
  206.  * n ==  0  :   only until line equalizes (from text_write())
  207.  *
  208.  * What is a paragraph?   A paragraph ends whenever the left justification
  209.  * gets larger, or on a blank line.
  210.  */
  211.  
  212. do_reformat(n)
  213. {
  214.     register char *str;
  215.     register ED *ep = Ep;
  216.     int nlok, lnsc, fnst, fnsc;
  217.     int column = ep->Column;
  218.     int srow   = ep->Line;
  219.     int crow   = srow;
  220.     int erow   = srow;
  221.     short dins = 0;         /* relative insert lines/delete lines   */
  222.     char moded = 0;         /* any modifications done at all?       */
  223.     char checked = 0;       /* for cursor positioning.              */
  224.  
  225.     if (ep->Margin == 0)
  226.         ep->Margin = 75;
  227.  
  228.     ++Nsu;
  229.     for (;;) {
  230.         str = (char *)ep->List[ep->Line+1];
  231.         fnst = 0;
  232.         fnsc = firstns(Current);
  233.         nlok = (ep->Line + 1 < ep->Lines && fnsc >= (fnst=firstns(str)));
  234.         if (nlok && str[0] == 0)
  235.             nlok = 0;
  236.         lnsc = lastns(Current);
  237.         if (lnsc < ep->Margin) {    /* space at end of line for marg-lnsc-2 letter word   */
  238.             if (nlok == 0)        /* but no more data to joinup   */
  239.                 break;            /* done */
  240.             if (ep->Margin - lnsc - 2 >= wordlen(str+fnst)) {
  241.                 ep->Column = 0;
  242.                 Clen = lastns(Current);
  243.                 if (Current[Clen])
  244.                     ++Clen;
  245.                 moded = 1;
  246.                 --dins;
  247.                 if (do_join())
  248.                     continue;
  249.                 ++dins;
  250.                 title("Error, Margin > 124");
  251.                 break;
  252.             }
  253.             if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  254.                 break;
  255.             do_down();
  256.             erow = ep->Line;
  257.             continue;
  258.         }
  259.                                 /* no space, need to split      */
  260.                                 /* find start of prev word      */
  261.         for (;;) {
  262.             register int i = lnsc;
  263.             while (i && Current[i] != ' ')
  264.                 --i;
  265.             lnsc = i;
  266.             if (i >= ep->Margin) {
  267.                 while (i && Current[i] == ' ')
  268.                     --i;
  269.                 if (i < ep->Margin)
  270.                     break;
  271.                 lnsc = i;
  272.                 continue;
  273.             }
  274.             break;
  275.         }
  276.         if (lnsc) {             /* ok to split at word          */
  277.             ++lnsc;
  278.             ++dins;
  279.             ep->Column = lnsc;
  280.             do_split(); /* Split at point LNSC          */
  281.             do_down();          /* must insert proper amount?   */
  282.             {
  283.                 int indent = (nlok == 0) ? fnsc : fnst;
  284.                 if (!checked) {
  285.                     checked = 1;
  286.                     if (lnsc <= column) {   /* if split before cursor   */
  287.                         column = column - ep->Column + indent;
  288.                         ++crow;
  289.                     }
  290.                 }
  291.                 if (Clen + indent < 253) {
  292.                     bmov(Current, Current + indent, strlen(Current)+1);
  293.                     bset(Current, indent, ' ');
  294.                     Clen += indent;
  295.                 }
  296.             }
  297.             erow = ep->Line;
  298.             continue;
  299.         }
  300.         if (n == 0)
  301.             break;
  302.         do_down();
  303.     }
  304.     if (column < 0 || column > 200)
  305.         column = 0;
  306.     if (srow >= ep->Lines) {
  307.         srow = ep->Lines - 1;
  308.         goto ra;
  309.     }
  310.     if (dins || srow < ep->Topline || srow >= ep->Topline + Rows) {
  311. ra:
  312.         text_sync();
  313.         --Nsu;
  314.         ep->Line = crow;
  315.         ep->Column = column;
  316.         text_load();
  317.         if (!text_sync())
  318.             text_redisplay();
  319.     } else {
  320.         text_sync();
  321.         --Nsu;
  322.         ep->Line = crow;
  323.         ep->Column = column;
  324.         text_load();
  325.         if (erow != srow) {
  326.             if (!text_sync()) {
  327.                 ++erow;
  328.                 if (erow - ep->Topline > Rows)
  329.                     erow = ep->Topline + Rows;
  330.                 SetAPen(Rp, 0);
  331.                 RectFill(Rp, COL(0), ROW(srow - ep->Topline), Xbase+Xpixs, ROW(erow - ep->Topline)-1);
  332.                 SetAPen(Rp, 1);
  333.                 text_displayseg(srow - ep->Topline, erow - srow);
  334.             }
  335.         } else {
  336.             text_sync();
  337.             if (moded)
  338.                 text_redisplaycurrline();
  339.         }
  340.     }
  341.     if (column > Clen) {
  342.         bset(Current+Clen, column - Clen, ' ');
  343.         Current[column] = 0;
  344.     }
  345.     ep->Column = column;
  346. }
  347.  
  348. do_tabstop()
  349. {
  350.     Ep->Tabstop = atoi(av[1]);
  351. }
  352.  
  353. do_insertmode()
  354. {
  355.     register ED *ep = Ep;
  356.  
  357.     if (av[1][0]) {
  358.         switch(av[1][1] & 0x1F) {
  359.         case 'n'&0x1F:
  360.             ep->Insertmode = 1;
  361.             break;
  362.         case 'f'&0x1F:
  363.             ep->Insertmode = 0;
  364.             break;
  365.         case 'o'&0x1F:
  366.             ep->Insertmode = 1 - ep->Insertmode;
  367.             break;
  368.         }
  369.         if (ep->Insertmode)
  370.             title("Insert mode on");
  371.         else
  372.             title("Insert mode off");
  373.     }
  374. }
  375.  
  376. do_insline()
  377. {
  378.     register ubyte *ptr;
  379.     register ED *ep = Ep;
  380.  
  381.     ep->Modified = 1;
  382.     text_sync();
  383.     if (makeroom(32) && (ptr = allocb(1))) {
  384. #if M2ERR
  385.         if(Ep->err_num > 0)
  386.           err_insline();
  387. #endif
  388.         bmovl(ep->List+ep->Line, ep->List+ep->Line+1,ep->Lines-ep->Line);
  389.         ep->List[ep->Line] = ptr;
  390.         *ptr = 0;
  391.         ++ep->Lines;
  392.         if (BEp == ep) {
  393.             if (ep->Line < BSline)
  394.                 ++BSline;
  395.             if (ep->Line <= BEline)
  396.                 ++BEline;
  397.         }
  398.     } else {
  399.         nomemory();
  400.     }
  401.     text_load();
  402.     if (Nsu == 0)
  403.         ScrollRaster(Rp,0,-Ysize, COL(0), ROW(ep->Line-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  404.     text_displayseg(ep->Line - ep->Topline, 1);
  405. }
  406.  
  407. do_deline()
  408. {
  409.     register int delline;
  410.     register ED *ep = Ep;
  411.  
  412.     if (ep->Lines > 1) {
  413.         ep->Modified = 1;
  414.         text_sync();
  415. #if M2ERR
  416.         if(Ep->err_num > 0)
  417.           err_deline(Ep->Line);
  418. #endif
  419.         strcpy(Deline,ep->List[ep->Line]);
  420.         FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  421.         bmovl(ep->List+ep->Line+1, ep->List+ep->Line,ep->Lines-ep->Line-1);
  422.         if (BEp == ep) {
  423.             if (ep->Line < BSline)
  424.                 --BSline;
  425.             if (ep->Line <= BEline)
  426.                 --BEline;
  427.         }
  428.         delline = ep->Line;
  429.         if (ep->Line >= --ep->Lines) {
  430.             --ep->Line;
  431.             text_load();
  432.             if (ep->Line < ep->Topline) {
  433.                 if (Nsu == 0) {
  434.                     ep->Topline = ep->Line - (Rows>>1);
  435.                     if (ep->Topline < 0)
  436.                         ep->Topline = 0;
  437.                     text_redisplay();
  438.                 }
  439.                 return(0);
  440.             }
  441.         }
  442.         text_load();
  443.         if (Nsu == 0)
  444.             ScrollRaster(Rp,0,Ysize, COL(0), ROW(delline-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  445.         text_displayseg(Rows-1, 1);
  446.     } else {
  447.         do_firstcolumn();
  448.         do_remeol();
  449.         ep->Modified = 0;
  450.     }
  451. }
  452.  
  453. do_undeline()
  454. {
  455.    do_insline();
  456.    text_load();
  457.    strcpy(Current,Deline);
  458.    text_sync();
  459.    text_displayseg(Ep->Line - Ep->Topline, 1);
  460. }
  461.  
  462. do_chfilename()
  463. {
  464.     text_sync();
  465.     strncpy(Ep->Name, av[1], 63);
  466.     MForceTitle = 1;
  467. }
  468.  
  469. do_edit()
  470. {
  471.     long xfi;
  472.     long oldlock;
  473.     long lines;
  474.     ubyte buf[256];
  475.     ubyte *ptr;
  476.     char failed = 1;
  477.     register ED *ep = Ep;
  478.  
  479.     text_sync();
  480.     if (*av[0] == 'n') {        /* newfile or insfile   */
  481.         if (ep->Modified && getyn("Delete modified Image?") == 0)
  482.             return(0);
  483.         ep = uninit_init(ep);
  484.         strncpy(ep->Name, av[1], 63);
  485.     } else {
  486.         ep->Modified = 1;
  487.     }
  488.     lines = ep->Lines;
  489.     oldlock = CurrentDir(ep->dirlock);
  490.     proc->pr_WindowPtr = (APTR)Ep->Win;
  491.     if (xfi = xfopen(av[1], "r", 4096)) {
  492.         register int len;
  493.         char oktitle = 1;
  494.  
  495.         title("Loading...");
  496.         while ((len = xefgets(xfi, buf, 255)) >= 0) {
  497.             failed = 0;
  498.             if (makeroom(256) && (ptr = allocb(len+1))) {
  499.                 ep->List[ep->Lines++] = ptr;
  500.                 bmov(buf, ptr, len+1);
  501.             } else {
  502.                 set_window_params();
  503.                 nomemory();
  504.                 oktitle = 0;
  505.                 break;
  506.             }
  507.         }
  508.         set_window_params();
  509.         if (oktitle)
  510.             title("OK");
  511.     } else {
  512.         title("File Not Found");
  513. #if AREXX
  514.         cmderr = CMD_FAILED;
  515. #endif
  516.     }
  517.     xfclose(xfi);
  518.     CurrentDir(oldlock);
  519.     if (ep->Lines != 1 && lines == 1 && ep->List[0][0] == 0) {
  520.         ep->Modified = 0;
  521.         ep->Line = 0;
  522.         FreeMem(ep->List[0], strlen(ep->List[0])+1);
  523.         bmovl(ep->List+1, ep->List,--ep->Lines);
  524.     } else {
  525.         if (!failed && lines <= ep->Lines - 1) {
  526.             BEp = ep;
  527.             BSline = lines;
  528.             BEline = ep->Lines - 1;
  529.             do_bmove();
  530.         }
  531.     }
  532.     set_window_params();
  533. #if M2ERR
  534.     read_errfile();
  535. #endif
  536.     text_load();
  537.     text_redisplay();
  538. }
  539.  
  540.  
  541. static char blockmode;
  542.  
  543. do_bsave()
  544. {
  545.     blockmode = 1;
  546.     do_saveas();
  547. }
  548.  
  549. do_save()
  550. {
  551.     av[1] = Ep->Name;
  552.     do_saveas();
  553. }
  554.  
  555. do_savetabs()
  556. {
  557.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  558. }
  559.  
  560. do_saveas()
  561. {
  562.     long oldlock;
  563.     long xfi;
  564.     register long i;
  565.     register short j, k;
  566.     register ubyte *ptr, *bp;
  567.     long xs, xe;
  568.     ubyte buf[256];
  569.     char bm;
  570.     ED *ep;
  571.  
  572.     bm = blockmode;
  573.     if (blockmode && blockok()) {
  574.         xs = BSline;
  575.         xe = BEline + 1;
  576.         ep = BEp;
  577.     } else {
  578.         xs = 0;
  579.         xe = Ep->Lines;
  580.         ep = Ep;
  581.     }
  582.     blockmode = 0;
  583.     text_sync();
  584.     oldlock = CurrentDir(Ep->dirlock);
  585.     if (Wbs && Wdisable == 0) {     /* Write out .info file */
  586.         DISKOBJ sdo, *d;
  587.         bzero(&sdo, sizeof(sdo));
  588.         if ((d = GetDiskObject(av[1])) == NULL) {
  589.             if (getpath(Wbs->sm_ArgList[0].wa_Name, buf)) {
  590.                 sdo.do_Magic = WB_DISKMAGIC;
  591.                 sdo.do_Version = WB_DISKVERSION;
  592.                 makemygadget(&sdo.do_Gadget);
  593.                 sdo.do_Type = WBPROJECT;
  594.                 sdo.do_DefaultTool = (char *)buf;
  595.                 sdo.do_ToolTypes = NULL;
  596.                 sdo.do_CurrentX = NO_ICON_POSITION;
  597.                 sdo.do_CurrentY = NO_ICON_POSITION;
  598.                 sdo.do_DrawerData = NULL;
  599.                 sdo.do_ToolWindow = NULL;
  600.                 sdo.do_StackSize = 8192;
  601.                 PutDiskObject(av[1], &sdo);
  602.             }
  603.         } else {
  604.             FreeDiskObject(d);
  605.         }
  606.     }
  607.     proc->pr_WindowPtr = (APTR)Ep->Win;
  608.     if (xfi = xfopen(av[1], "w", 4096)) {
  609.         title("Saving...");
  610.         for (i = xs; i < xe; ++i) {
  611.             ptr = ep->List[i];
  612.             if (Savetabs) {
  613.                 for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  614.                     *bp = *ptr;
  615.                     if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  616.                         k = j;
  617.                         while (k-- >= 0 && *bp == ' ')
  618.                             --bp;
  619.                         *++bp = 9;
  620.                     } else {
  621.                         if (*bp == '\"' || *bp == '\'' || *bp == '\`' || *bp == '(')
  622.                             break;
  623.                     }
  624.                 }
  625.                 strcpy(bp, ptr);
  626.                 ptr = buf;
  627.             }
  628.             xfwrite(xfi, ptr, strlen(ptr));
  629.             if (xfwrite(xfi, "\n", 1)) {
  630.                 xfclose(xfi);
  631.                 goto err;
  632.             }
  633.         }
  634.         if (xfclose(xfi)) {
  635. err:        Abortcommand = 1;
  636.             title("WRITE FAILED!");
  637.         } else {
  638.             ep->Modified &= bm;
  639.             title("OK");
  640.         }
  641.     } else {
  642.         title("Unable to open write file");
  643.         Abortcommand = 1;
  644.     }
  645.     CurrentDir(oldlock);
  646. }
  647.  
  648. do_block()          /* block, unblock   */
  649. {
  650.     text_sync();
  651.  
  652.     switch(av[0][0]) {
  653.     case 'b':
  654.         if (BSline < 0) {
  655. bstart:
  656.             BEp = Ep;
  657.             BSline = Ep->Line;
  658.             title("Block Begin");
  659.         } else {
  660.             if (BEline > -1) {
  661.                 title("Block Already Marked");
  662.                 break;
  663.             }
  664.             if (BEp != Ep)
  665.                 goto bstart;
  666.             title("Block End");
  667.             BEline = Ep->Line;
  668.             if (BSline > BEline) {
  669.                 BEline = BSline;
  670.                 BSline = Ep->Line;
  671.             }
  672.             text_redrawblock(1);
  673.         }
  674.         break;
  675.     case 'u':
  676.         text_redrawblock(0);
  677.         title ("Block Unmarked");
  678.         break;
  679.     }
  680. }
  681.  
  682.  
  683. blockok()
  684. {
  685.     if (BEp && BSline >= 0 && BSline <= BEline && BEline < BEp->Lines)
  686.         return(1);
  687.     BEp = NULL;
  688.     BSline = BEline = -1;
  689.     title("Block Not Specified");
  690.     return(0);
  691. }
  692.  
  693.  
  694. do_bdelete()
  695. {
  696.     register long i, n;
  697.     register ED *bep = BEp;
  698.     register WIN *savewin = Ep->Win;
  699.  
  700.     if (blockok()) {
  701.         text_switch(bep->Win);
  702.         n = BEline - BSline + 1;
  703. #if M2ERR
  704.         if(Ep->err_num > 0)
  705.           for(i = BSline; i <= BEline ; i++)
  706.             err_deline(i);
  707. #endif
  708.         if (bep->Line >= BSline && bep->Line <= BEline)
  709.             bep->Line = BSline;
  710.         if (bep->Line > BEline)
  711.             bep->Line -= n;
  712.         freelist(bep->List + BSline, BEline - BSline + 1);
  713.         bmovl(bep->List+BEline+1,bep->List+BSline,(bep->Lines-BEline-1));
  714.         bep->Lines -= n;
  715.         bep->Modified = 1;
  716.         if (bep->Line >= bep->Lines)
  717.             bep->Line = bep->Lines - 1;
  718.         if (bep->Line < 0)
  719.             bep->Line = 0;
  720.         if (bep->Lines == 0)
  721.             bep = uninit_init(bep);
  722.         text_load();
  723.         BEp = NULL;
  724.         BSline = BEline = -1;
  725.         if (!text_sync())
  726.             text_redisplay();
  727.         text_switch(savewin);
  728.     }
  729. }
  730.  
  731. void
  732. do_bcopy()
  733. {
  734.     register ubyte **list;
  735.     register long lines, i;
  736.     register ED *ep = Ep;
  737.  
  738.     text_sync();
  739.     if (!blockok())
  740.         return;
  741.     if (ep == BEp && ep->Line > BSline && ep->Line <= BEline) {
  742.         title("Cannot Move into self");
  743.         return;
  744.     }
  745.  
  746.     lines = BEline - BSline + 1;
  747.     if (extend(ep, lines)) {
  748.         if (list = (ubyte **)allocl(lines)) {
  749. #if M2ERR
  750.             Ep->err_num = -1;
  751. #endif
  752.             bmovl(BEp->List+BSline,list,lines);
  753.             bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  754.             for (i = 0; i < lines; ++i) {
  755.                 ubyte *str = allocb(strlen(list[i])+1);
  756.                 if (!str) {
  757.                     nomemory();
  758.                     FreeMem(list, lines * sizeof(char *));
  759.                     freelist(ep->List + Ep->Line, i);
  760.                     bmovl(ep->List+ep->Line+lines, ep->List+ep->Line, ep->Lines-ep->Line);
  761.                     return;
  762.                 }
  763.                 strcpy(str, list[i]);
  764.                 ep->List[ep->Line+i] = str;
  765.             }
  766.             FreeMem(list, lines * sizeof(char *));
  767.         }
  768.     }
  769.     if (ep == BEp && ep->Line <= BSline) {
  770.         BSline += lines;
  771.         BEline += lines;
  772.     }
  773.     ep->Modified = 1;
  774.     ep->Lines += lines;
  775.     text_load();
  776.     if (!text_sync())
  777.         text_redisplay();
  778. }
  779.  
  780.  
  781. void
  782. do_bmove()
  783. {
  784.     register long lines;
  785.     register ubyte **list;
  786.     register ED *ep = Ep;
  787.  
  788.     text_sync();
  789.     if (!blockok())
  790.         return;
  791.     if (BEp == ep && ep->Line >= BSline && ep->Line <= BEline) {
  792.         title("Cannot Move into self");
  793.         return;
  794.     }
  795.     lines = BEline - BSline + 1;
  796.     if (!(list = (ubyte **)allocl(lines))) {
  797.         nomemory();
  798.         return;
  799.     }
  800. #if M2ERR
  801.     Ep->err_num = -1;
  802. #endif
  803.     BEp->Modified = ep->Modified = 1;
  804.     bmovl(BEp->List + BSline, list, lines);
  805.     if (ep == BEp) {
  806.         if (ep->Line > BSline) {
  807.             bmovl(ep->List+BEline+1, ep->List+BSline, ep->Line-BEline-1);
  808.             bmovl(list, ep->List + ep->Line - lines, lines);
  809.         } else {
  810.             bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, BSline-ep->Line);
  811.             bmovl(list, ep->List + ep->Line, lines);
  812.         }
  813.     } else {
  814.         WIN *savewin = ep->Win;
  815.         if (extend(ep, lines)) {
  816.             bmovl(BEp->List+BEline+1, BEp->List+BSline, BEp->Lines-BEline-1);
  817.             bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  818.             bmovl(list, ep->List+ep->Line, lines);
  819.             ep->Lines += lines;
  820.             BEp->Lines -= lines;
  821.             if (BEp->Line >= BSline && BEp->Line <= BEline)
  822.                 BEp->Line = BSline - 1;
  823.             if (BEp->Line > BEline)
  824.                 BEp->Line -= lines;
  825.             if (BEp->Line < 0)
  826.                 BEp->Line = 0;
  827.             BSline = BEline = -1;
  828.             if (BEp->Lines == 0) {
  829.                 register ubyte *ptr = allocb(1);
  830.                 BEp->List[0] = ptr;
  831.                 *ptr = 0;
  832.                 ++BEp->Lines;
  833.             }
  834.             text_load();
  835.             text_switch(BEp->Win);
  836.             BEp = NULL;
  837.             ep = Ep;
  838.             if (!ep->iconmode) {
  839.                 if (!text_sync())
  840.                     text_redisplay();
  841.             }
  842.             text_switch(savewin);
  843.             ep = Ep;
  844.         }
  845.     }
  846.     BSline = BEline = -1;
  847.     BEp = NULL;
  848.     FreeMem(list, lines * sizeof(char *));
  849.     ep->Modified = 1;
  850.     text_load();
  851.     if (!text_sync())
  852.         text_redisplay();
  853. }
  854.  
  855.  
  856. /*
  857.  * IF condition trueaction, IFELSE condition trueaction falseaction
  858.  *
  859.  *  condition:  !condition NOT the specified condition.
  860.  *              #          toggle number is SET
  861.  *              top        top of file (on first line)
  862.  *              bot        end of file (on last line)
  863.  *              left       start of line (leftmost column)
  864.  *              right      end of line (nothing but spaces under and to the right)
  865.  *              modified   text has been modified
  866.  *              insert     currently in insert mode
  867.  *              y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  868.  *              x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  869.  *                          <> means 'not equal'
  870.  *
  871.  *              cl         char under cursor is lower case
  872.  *              cu         char under cursor is upper case
  873.  *              ca         char under cursor is alpha
  874.  *              cn         char under cursor is numeric
  875.  *              cb         char within selected block
  876.  *              c[<=>]#    char under cursor is (combo of <,>,and =) #
  877.  */
  878.  
  879. do_if()
  880. {
  881.     char haselse = (av[0][2] == 'e');
  882.     char iswhile = (av[0][0] == 'w');
  883.     char istrue, notop = 0;
  884.     char c, cx, cc;
  885.     ubyte *buf1, *buf2;
  886.     register ubyte *ptr;
  887.     register ED *ep = Ep;
  888.     int i, cxn, cn;
  889.  
  890.     buf1 = (ubyte *)malloc(256);
  891.     buf2 = (ubyte *)malloc(256);
  892.     if (buf1 == NULL || buf2 == NULL) {
  893.         if (buf1) free(buf1);
  894.         if (buf2) free(buf2);
  895.         title("No Memory!");
  896.         return(0);
  897.     }
  898.     breakreset();
  899.     ptr = av[1];
  900.     if (*ptr == '!') {
  901.         notop = 1;
  902.         ++ptr;
  903.     }
  904.     c = ptr[0];
  905.     cn= atoi(ptr);
  906.     cx= ptr[1];
  907.     cxn=atoi(ptr+1);
  908.     strcpy(buf1, av[2]);
  909.  
  910. loop:
  911.     istrue = 0;
  912.     i = 0;
  913.     switch(c) {
  914.     case 'x':
  915.         i = ep->Column + 1;
  916.     case 'y':
  917.         if (!i)
  918.             i = ep->Line + 1;
  919. conditional:
  920.         {
  921.             register int j, n;
  922.             char any = 0;
  923.  
  924.             for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
  925.             n = atoi(ptr+j);
  926.             for (j = 1; ptr[j]; ++j) {
  927.                 switch(ptr[j]) {
  928.                 case '<':
  929.                     any = 1;
  930.                     if (i < n)
  931.                         istrue = 1;
  932.                     break;
  933.                 case '=':
  934.                     any = 1;
  935.                     if (i == n)
  936.                         istrue = 1;
  937.                     break;
  938.                 case '>':
  939.                     any = 1;
  940.                     if (i > n)
  941.                         istrue = 1;
  942.                     break;
  943.                 }
  944.             }
  945.             if (!any && i == n)  /* default is equivalence   */
  946.                 istrue = 1;
  947.         }
  948.         break;
  949.     case 't':
  950.         istrue = ep->Line == 0;
  951.         break;
  952.     case 'b':
  953.         istrue = ep->Line == ep->Lines-1;
  954.         break;
  955.     case 'l':
  956.         istrue = ep->Column == 0;
  957.         break;
  958.     case 'r':
  959.         istrue = ep->Column == Clen;
  960.         break;
  961.     case 'm':
  962.         text_sync();
  963.         istrue = ep->Modified != 0;
  964.         break;
  965.     case 'i':
  966.         istrue = ep->Insertmode != 0;
  967.         break;
  968.     case 'c':
  969.         cc = Current[ep->Column];
  970.         switch(cx) {
  971.         case 'b':
  972.             istrue = BEp == ep && ep->Line >= BSline && ep->Line <= BEline;
  973.             break;
  974.         case 'l':
  975.             istrue = cc >= 'a' && cc <= 'z';
  976.             break;
  977.         case 'u':
  978.             istrue = cc >= 'A' && cc <= 'Z';
  979.             break;
  980.         case 'a':
  981.             istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
  982.             break;
  983.         case 'n':
  984.             istrue = (cc >= '0' && cc <= '9');
  985.             break;
  986.         default:                /* c[<=>]#  */
  987.             i = Current[ep->Column];
  988.             goto conditional;
  989.             break;
  990.         }
  991.         break;
  992.     default:
  993.         if (c >= '0' && c <= '9')
  994.             istrue = do_toggle(cn) != 0;
  995.         else
  996.             title("bad conditional");
  997.         break;
  998.     }
  999.     istrue ^= notop;
  1000.     if (istrue) {
  1001.         strcpy(buf2, buf1);     /* could be executed multiple times */
  1002.         if (do_command(buf2) == 0)
  1003.             goto done;
  1004.         if (iswhile) {
  1005.             if (breakcheck())
  1006.                 Abortcommand = 1;
  1007.             else
  1008.                 goto loop;
  1009.         }
  1010.     } else {
  1011.         if (haselse) {          /* only executed once */
  1012.             strcpy(buf2, av[3]);
  1013.             do_command(buf2);
  1014.         }
  1015.     }
  1016. done:
  1017.     free(buf1);
  1018.     free(buf2);
  1019. }
  1020.  
  1021.  
  1022. /*
  1023.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  1024.  */
  1025.  
  1026. do_toggle(n)
  1027. {
  1028.     static char tg[MAXTOGGLE];
  1029.     register int i;
  1030.  
  1031.     if (n >= 0) {
  1032.         if (n >= MAXTOGGLE)
  1033.             return(0);
  1034.         return(tg[n]);
  1035.     }
  1036.     i = atoi(av[1]);
  1037.     if (i >= 0 && i < MAXTOGGLE) {
  1038.         switch(av[0][0]) {
  1039.         case 't':
  1040.             tg[i] = !tg[i];
  1041.             break;
  1042.         case 's':
  1043.             tg[i] = 1;
  1044.             break;
  1045.         case 'r':
  1046.             tg[i] = 0;
  1047.             break;
  1048.         }
  1049.     }
  1050. }
  1051.  
  1052.  
  1053. do_tlate()
  1054. {
  1055.     register ubyte *ptr = av[1];
  1056.     register ED *ep = Ep;
  1057.     register char c = Current[ep->Column];
  1058.  
  1059.     if (c == 0)
  1060.         c = ' ';
  1061.     if (ptr[0] == '+')
  1062.         c += atoi(ptr+1);
  1063.     else
  1064.     if (ptr[0] == '-')
  1065.         c -= atoi(ptr+1);
  1066.     else
  1067.         c = atoi(ptr);
  1068.     if (c) {
  1069.         if (Current[ep->Column] == 0) {
  1070.             Clen = ep->Column + 1;
  1071.             Current[Clen] = 0;
  1072.         }
  1073.         Current[ep->Column] = c;
  1074.         if (Nsu == 0) {
  1075.             movetocursor();
  1076.             setpen(ep->Line);
  1077.             Text(Rp, Current+ep->Column, 1);
  1078.         }
  1079.     }
  1080. }
  1081.  
  1082. /*
  1083.  *  BSOURCE
  1084.  *
  1085.  *  note that since the start and end lines are loaded immediately and the
  1086.  *  block unblock'd before execution starts, you can theoretically have
  1087.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  1088.  */
  1089.  
  1090. do_bsource()
  1091. {
  1092.     ubyte buf[256];
  1093.     register int i, sl, se;
  1094.  
  1095.     if (blockok()) {
  1096.         sl = BSline;
  1097.         se = BEline + 1;
  1098.         for (i = sl; BEp && i < se && i < BEp->Lines; ++i) {
  1099.             text_sync();        /* make sure we are using latest text */
  1100.             strcpy(buf, BEp->List[i]);
  1101.             if (do_command(buf) == 0)
  1102.                 break;
  1103.         }
  1104.         text_redrawblock(0);
  1105.     }
  1106. }
  1107.  
  1108. /*
  1109.  *  SCANF controlstring
  1110.  *
  1111.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  1112.  *  control string.
  1113.  */
  1114.  
  1115. void
  1116. do_scanf()
  1117. {
  1118.     char buf[256];
  1119.  
  1120.     buf[0] = 0;
  1121.     sscanf(Current+Ep->Column,av[1],buf,buf,buf,buf,buf,buf,buf);
  1122.     if (String)
  1123.         free(String);
  1124.     String = (char *)malloc(strlen(buf)+1);
  1125.     strcpy(String,buf);
  1126.     title(String);
  1127. }
  1128.  
  1129. do_abort()
  1130. {
  1131.     Abortcommand = 1;
  1132. }
  1133.  
  1134. movetocursor()
  1135. {
  1136.     register ED *ep = Ep;
  1137.     Move(Rp, XTbase+(ep->Column-ep->Topcolumn)*Xsize, YTbase+(ep->Line-ep->Topline)*Ysize);
  1138. }
  1139.  
  1140. extend(ep, lines)
  1141. register ED *ep;
  1142. {
  1143.     register long extra = ep->Maxlines - ep->Lines;
  1144.     register ubyte **list;
  1145.  
  1146.     if (lines > extra) {
  1147.         lines += ep->Lines;
  1148.         if (list = (ubyte **)allocl(lines)) {
  1149.             bmovl(ep->List, list, ep->Lines);
  1150.             FreeMem(ep->List, sizeof(char *) * ep->Maxlines);
  1151.             ep->Maxlines = lines;
  1152.             ep->List = list;
  1153.             return(1);
  1154.         }
  1155.         nomemory();
  1156.         return(0);
  1157.     }
  1158.     return(1);
  1159. }
  1160.  
  1161. makeroom(n)
  1162. {
  1163.     register ED *ep = Ep;
  1164.     if (ep->Lines >= ep->Maxlines)
  1165.         return(extend(ep, n));
  1166.     return(1);
  1167. }
  1168.  
  1169. freelist(list, n)
  1170. register char **list;
  1171. {
  1172.     while (n) {
  1173.         FreeMem(list[0], strlen(list[0])+1);
  1174.         ++list;
  1175.         --n;
  1176.     }
  1177. }
  1178.  
  1179.